package cn.yx.common.web.controller;

import cn.yx.common.core.controller.BaseAdminController;
import cn.yx.common.core.mapping.DtoVoMapping;
import cn.yx.common.core.pojo.*;
import cn.yx.common.core.pojo.singletable.SingleCond;
import cn.yx.common.core.pojo.singletable.SingleDto;
import cn.yx.common.core.pojo.singletable.SingleInVo;
import cn.yx.common.core.pojo.singletable.SingleOutVo;
import cn.yx.common.core.service.BaseService;
import cn.yx.common.web.constant.message.AbstractBaseControllerMessageKey;

import java.io.Serializable;
import java.util.List;

/**
 * <p>后台管理Controller类的父类，操作单表</p>
 *
 * @param <InVo>  VO输入类
 * @param <OutVo> VO输出类
 * @param <Dto>   DTO类
 * @param <Cond>  Cond类
 * @param <Id>    ID主键值类
 * @author Wgssmart
 */
public abstract class AbstractAdminController<InVo extends SingleInVo,
        OutVo extends SingleOutVo,
        Dto extends SingleDto,
        Cond extends SingleCond,
        Id extends Serializable>
        implements BaseAdminController<InVo, OutVo, Cond, Id> {

    private final BaseService<Dto, Cond, Id> service;

    private final DtoVoMapping<Dto, InVo, OutVo> mapping;

    public AbstractAdminController(BaseService<Dto, Cond, Id> service, DtoVoMapping<Dto, InVo, OutVo> mapping) {
        this.service = service;
        this.mapping = mapping;
    }

    @Override
    public ResponseVo<Void> save(InVo inVo) {
        boolean saved = service.save(mapping.inVoToDto(inVo));
        return saved ? ResponseVo.ok(AbstractBaseControllerMessageKey.SAVE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.SAVE_FAIL);
    }

    @Override
    public ResponseVo<Void> save(List<InVo> inVoList) {
        boolean saved = service.save(mapping.inVoToDto(inVoList));
        return saved ? ResponseVo.ok(AbstractBaseControllerMessageKey.BATCH_SAVE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.BATCH_SAVE_FAIL);
    }

    @Override
    public ResponseVo<Void> saveOrUpdate(InVo inVo) {
        boolean savedOrUpdated = service.saveOrUpdate(mapping.inVoToDto(inVo));
        return savedOrUpdated ? ResponseVo.ok(AbstractBaseControllerMessageKey.SAVE_OR_UPDATE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.SAVE_OR_UPDATE_FAIL);
    }

    @Override
    public ResponseVo<Void> saveOrUpdate(InVo inVo, Cond updateCond) {
        boolean savedOrUpdated = service.saveOrUpdate(mapping.inVoToDto(inVo), updateCond);
        return savedOrUpdated ? ResponseVo.ok(AbstractBaseControllerMessageKey.SAVE_OR_UPDATE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.SAVE_OR_UPDATE_FAIL);
    }

    @Override
    public ResponseVo<Void> saveOrUpdate(List<InVo> inVoList) {
        boolean savedOrUpdated = service.saveOrUpdate(mapping.inVoToDto(inVoList));
        return savedOrUpdated ? ResponseVo.ok(AbstractBaseControllerMessageKey.BATCH_SAVE_OR_UPDATE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.BATCH_SAVE_OR_UPDATE_FAIL);
    }

    @Override
    public ResponseVo<Void> remove(IdCond<Id> idCond) {
        boolean removed = service.remove(idCond.getId());
        return removed ? ResponseVo.ok(AbstractBaseControllerMessageKey.REMOVE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.REMOVE_FAIL);
    }

    @Override
    public ResponseVo<Void> remove(IdListCond<Id> idListCond) {
        boolean removed = service.remove(idListCond.getIdList());
        return removed ? ResponseVo.ok(AbstractBaseControllerMessageKey.BATCH_REMOVE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.BATCH_REMOVE_FAIL);
    }

    @Override
    public ResponseVo<Void> remove(Cond deleteCond) {
        boolean removed = service.remove(deleteCond);
        return removed ? ResponseVo.ok(AbstractBaseControllerMessageKey.REMOVE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.REMOVE_FAIL);
    }

    @Override
    public ResponseVo<Void> update(InVo inVo) {
        boolean updated = service.update(mapping.inVoToDto(inVo));
        return updated ? ResponseVo.ok(AbstractBaseControllerMessageKey.UPDATE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.UPDATE_FAIL);
    }

    @Override
    public ResponseVo<Void> update(List<InVo> inVoList) {
        boolean updated = service.update(mapping.inVoToDto(inVoList));
        return updated ? ResponseVo.ok(AbstractBaseControllerMessageKey.BATCH_UPDATE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.BATCH_UPDATE_FAIL);
    }

    @Override
    public ResponseVo<Void> update(InVo inVo, Cond updateCond) {
        boolean updated = service.update(mapping.inVoToDto(inVo), updateCond);
        return updated ? ResponseVo.ok(AbstractBaseControllerMessageKey.UPDATE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.UPDATE_FAIL);
    }

    @Override
    public ResponseVo<Void> updateAllColumn(InVo inVo) {
        boolean updated = service.updateAllColumn(mapping.inVoToDto(inVo));
        return updated ? ResponseVo.ok(AbstractBaseControllerMessageKey.UPDATE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.UPDATE_FAIL);
    }

    @Override
    public ResponseVo<Void> updateAllColumn(List<InVo> inVoList) {
        boolean updated = service.updateAllColumn(mapping.inVoToDto(inVoList));
        return updated ? ResponseVo.ok(AbstractBaseControllerMessageKey.BATCH_UPDATE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.BATCH_UPDATE_FAIL);
    }

    @Override
    public ResponseVo<Void> updateAllColumn(InVo inVo, Cond updateCond) {
        boolean updated = service.updateAllColumn(mapping.inVoToDto(inVo), updateCond);
        return updated ? ResponseVo.ok(AbstractBaseControllerMessageKey.UPDATE_SUCCESS)
                : ResponseVo.fail(AbstractBaseControllerMessageKey.UPDATE_FAIL);
    }

    @Override
    public ResponseVo<OutVo> getOne(IdCond<Id> idCond) {
        Dto dto = service.getOne(idCond.getId());
        return ResponseVo.ok(AbstractBaseControllerMessageKey.SELECT_SUCCESS, mapping.dtoToOutVo(dto));
    }

    @Override
    public ResponseVo<OutVo> getOne(Cond selectCond) {
        Dto dto = service.getOne(selectCond, true);
        return ResponseVo.ok(AbstractBaseControllerMessageKey.SELECT_SUCCESS, mapping.dtoToOutVo(dto));
    }

    @Override
    public ResponseVo<PageVo<OutVo>> listAll() {
        List<Dto> dtoList = service.listAll();
        PageVo<OutVo> pageVo = new PageVo<>();
        pageVo.setTotal((long) dtoList.size());
        pageVo.setResults(mapping.dtoToOutVo(dtoList));
        return ResponseVo.ok(AbstractBaseControllerMessageKey.SELECT_SUCCESS, pageVo);
    }

    @Override
    public ResponseVo<PageVo<OutVo>> listAll(Cond selectCond) {
        List<Dto> dtoList = service.listAll(selectCond);
        PageVo<OutVo> pageVo = new PageVo<>();
        pageVo.setTotal((long) dtoList.size());
        pageVo.setResults(mapping.dtoToOutVo(dtoList));
        return ResponseVo.ok(AbstractBaseControllerMessageKey.SELECT_SUCCESS, pageVo);
    }

    @Override
    public ResponseVo<PageVo<OutVo>> listAll(IdListCond<Id> idListCond) {
        List<Dto> dtoList = service.listAll(idListCond.getIdList());
        PageVo<OutVo> pageVo = new PageVo<>();
        pageVo.setTotal((long) dtoList.size());
        pageVo.setResults(mapping.dtoToOutVo(dtoList));
        return ResponseVo.ok(AbstractBaseControllerMessageKey.SELECT_SUCCESS, pageVo);
    }

    @Override
    public ResponseVo<PageVo<OutVo>> page(Cond pageCond) {
        PageDto<Dto> pageDto = service.page(pageCond);
        PageVo<OutVo> pageVo = new PageVo<>();
        pageVo.setTotal(pageDto.getTotal());
        pageVo.setResults(mapping.dtoToOutVo(pageDto.getResults()));
        return ResponseVo.ok(AbstractBaseControllerMessageKey.SELECT_SUCCESS, pageVo);
    }

    @Override
    public ResponseVo<Long> count() {
        long count = service.count();
        return ResponseVo.ok(AbstractBaseControllerMessageKey.SELECT_SUCCESS, count);
    }

    @Override
    public ResponseVo<Long> count(Cond selectCond) {
        long count = service.count(selectCond);
        return ResponseVo.ok(AbstractBaseControllerMessageKey.SELECT_SUCCESS, count);
    }

}
